import Redis from 'ioredis';

// Redis 配置
const redisConfig = {
  host: process.env.REDIS_HOST || 'localhost',
  port: parseInt(process.env.REDIS_PORT || '6379'),
  password: process.env.REDIS_PASSWORD || undefined,
  db: parseInt(process.env.REDIS_DB || '0'),
  // 连接配置 - 简化配置
  lazyConnect: false,
  connectTimeout: 5000,
  commandTimeout: 3000,
  // 禁用自动重连
  retryDelayOnFailover: 0,
  maxRetriesPerRequest: 0,
  // 连接池配置
  family: 4,
  // 错误处理
  showFriendlyErrorStack: true,
};

class RedisManager {
  private client: Redis | null = null;
  private isConnecting = false;
  private connectionPromise: Promise<Redis> | null = null;

  /**
   * 获取 Redis 客户端实例
   */
  async getClient(): Promise<Redis> {
    if (this.client && this.client.status === 'ready') {
      return this.client;
    }

    if (this.isConnecting && this.connectionPromise) {
      return this.connectionPromise;
    }

    return this.createConnection();
  }

  /**
   * 创建新的连接
   */
  private async createConnection(): Promise<Redis> {
    if (this.isConnecting) {
      throw new Error('Redis 连接已在进行中');
    }

    this.isConnecting = true;
    this.connectionPromise = this.connectWithRetry();

    try {
      const client = await this.connectionPromise;
      this.client = client;
      return client;
    } finally {
      this.isConnecting = false;
      this.connectionPromise = null;
    }
  }

  /**
   * 带重试的连接
   */
  private async connectWithRetry(maxRetries = 3): Promise<Redis> {
    for (let attempt = 1; attempt <= maxRetries; attempt++) {
      try {
        console.log(`🔄 尝试连接 Redis (第 ${attempt} 次)...`);
        console.log('📋 Redis 配置:', {
          host: redisConfig.host,
          port: redisConfig.port,
          db: redisConfig.db,
          password: redisConfig.password ? '***' : '无',
          connectTimeout: redisConfig.connectTimeout
        });
        
        const client = new Redis(redisConfig);
        
        // 设置事件监听
        this.setupEventListeners(client);
        
        // 等待连接就绪
        await this.waitForReady(client);
        
        console.log('✅ Redis 连接成功');
        return client;
        
      } catch (error: any) {
        console.error(`❌ Redis 连接失败 (第 ${attempt} 次):`, error.message);
        
        if (attempt === maxRetries) {
          throw new Error(`Redis 连接失败，已重试 ${maxRetries} 次: ${error.message}`);
        }
        
        // 等待一段时间后重试
        await this.delay(1000 * attempt);
      }
    }
    
    throw new Error('Redis 连接失败');
  }

  /**
   * 设置事件监听器
   */
  private setupEventListeners(client: Redis): void {
    client.on('connect', () => {
      console.log('✅ Redis 连接建立');
    });

    client.on('ready', () => {
      console.log('✅ Redis 客户端就绪');
    });

    client.on('error', (error) => {
      console.error('❌ Redis 错误:', error.message);
    });

    client.on('close', () => {
      console.log('🔌 Redis 连接关闭');
      this.client = null;
    });

    client.on('end', () => {
      console.log('🏁 Redis 连接结束');
      this.client = null;
    });
  }

  /**
   * 等待连接就绪
   */
  private async waitForReady(client: Redis, timeout = 5000): Promise<void> {
    return new Promise((resolve, reject) => {
      const timer = setTimeout(() => {
        reject(new Error('Redis 连接超时'));
      }, timeout);

      if (client.status === 'ready') {
        clearTimeout(timer);
        resolve();
        return;
      }

      client.once('ready', () => {
        clearTimeout(timer);
        resolve();
      });

      client.once('error', (error) => {
        clearTimeout(timer);
        reject(error);
      });
    });
  }

  /**
   * 延迟函数
   */
  private delay(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  /**
   * 检查连接状态
   */
  async isConnected(): Promise<boolean> {
    try {
      const client = await this.getClient();
      await client.ping();
      return true;
    } catch (error) {
      console.error('Redis 连接检查失败:', error);
      return false;
    }
  }

  /**
   * 关闭连接
   */
  async close(): Promise<void> {
    if (this.client) {
      try {
        await this.client.quit();
        console.log('✅ Redis 连接已关闭');
      } catch (error) {
        console.error('❌ 关闭 Redis 连接失败:', error);
      } finally {
        this.client = null;
      }
    }
  }

  /**
   * 获取连接信息
   */
  getConnectionInfo(): {
    host: string;
    port: number;
    db: number;
    status: string;
  } {
    return {
      host: redisConfig.host,
      port: redisConfig.port,
      db: redisConfig.db,
      status: this.client?.status || 'disconnected'
    };
  }
}

// 创建全局 Redis 管理器实例
export const redisManager = new RedisManager();

// 导出便捷函数
export async function getRedisClient(): Promise<Redis> {
  return redisManager.getClient();
}

export async function checkRedisConnection(): Promise<boolean> {
  return redisManager.isConnected();
}

export async function closeRedisConnection(): Promise<void> {
  return redisManager.close();
}

export function getRedisInfo(): any {
  return redisManager.getConnectionInfo();
}

export default redisManager; 